package MineGod;

import org.lwjgl.opengl.GL11;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.opengl.Texture;

public abstract class EntityMob extends Entity{
	protected double hP;
	protected double maxHP;
	
	protected double y;
	
	protected double xSpeed;
	protected double ySpeed;
	protected double maxSpeed;
	
	private int invincible = 0; //Time left that player is invincible.
	private int fireInvincible = 0; //Time left that player is fire invincible.
	private int onFire = 0;
	
	protected double width;
	protected double height;

	protected double maskWidth;
	protected double maskHeight;
	
	public void damage(double dmg, DamageType src){
		if (src != DamageType.onFire && invincible == 0){
			hP -= dmg;		// This would be less if you didn't die instantly
			invincible = 500; // this would greater if you didn't die instantly
			if (src == DamageType.lava){
				onFire = 5000;
			}
		}else if (src == DamageType.onFire && fireInvincible == 0){
			hP-=dmg;
			fireInvincible = 270;
		}
		if (hP<=0){
			this.dead = true;
		}
	}
	
	public void updateOnFire(int delta){
		if (onFire > 0){
			onFire -= delta;
			this.damage(1, DamageType.onFire);
			if (Utils.pointToBlock(x+width/2, y+height/2).type == BlockType.water){
				onFire = 0;
			}
			if (onFire < 0){
				onFire = 0;
			}
			//System.out.println("invincibiliy: " + invincible);
		}
	}
	
	public void updateInvincibility(int delta){
		if (invincible > 0){
			invincible -= delta;
			if (invincible < 0){
				invincible = 0;
			}
			//System.out.println("invincibiliy: " + invincible);
		}
		if (fireInvincible > 0){
			fireInvincible -= delta;
			if (fireInvincible < 0){
				fireInvincible = 0;
			}
			//System.out.println("invincibiliy: " + invincible);
		}
	}
	
	public void horizontalPhysics(int delta, Chunk prevChunk, Chunk currChunk, Chunk nextChunk){
		Rectangle newMask = getNextMask((float)xSpeed*delta, 0f);
		CollisionGroup sideBlocks = getSideBlocks(prevChunk, currChunk, nextChunk, newMask);
		if (sideBlocks.bottomLeft.block == null || sideBlocks.bottomRight.block == null || sideBlocks.topLeft.block == null || sideBlocks.topRight.block == null){
			xSpeed = 0;
		}
		else
		{
			if (xSpeed > 0){
				for (BlockMask blockMask: new BlockMask[] {sideBlocks.topRight, sideBlocks.bottomRight}){
					if (blockMask.block != null && blockMask.block.isSolid && Utils.intersects(blockMask.mask, newMask)){
						xSpeed = 0;
						x = blockMask.xPos - width + (width-maskWidth)/2;
						break;
					}
				}
			} else if (xSpeed < 0) {
				for (BlockMask blockMask: new BlockMask[] {sideBlocks.topLeft, sideBlocks.bottomLeft}){
					if (blockMask.block != null && blockMask.block.isSolid && Utils.intersects(blockMask.mask, newMask)){
						xSpeed = 0;
						x = blockMask.xPos + Block.WIDTH - (width-maskWidth)/2;
						break;
					}
				}
			}
		}
	}
	
	public void climbingPhysics(int delta, Chunk prevChunk, Chunk currChunk, Chunk nextChunk){
		Rectangle newMask = getNextMask(0f, (float)ySpeed*delta);
		CollisionGroup sideBlocks = getSideBlocks(prevChunk, currChunk, nextChunk, newMask);
		if (sideBlocks.bottomLeft.block == null || sideBlocks.bottomRight.block == null || sideBlocks.topLeft.block == null || sideBlocks.topRight.block == null){
			ySpeed = 0;
		}
		else
		{
			if (ySpeed > 0){
				for (BlockMask blockMask: new BlockMask[] {sideBlocks.bottomLeft, sideBlocks.bottomRight}){
					if (blockMask.block != null && blockMask.block.isSolid && Utils.intersects(blockMask.mask, newMask)){
						ySpeed = 0;
						y = blockMask.yPos - height + (height-maskHeight)/2;
						break;
					}
				}
			} else if (ySpeed < 0) {
				for (BlockMask blockMask: new BlockMask[] {sideBlocks.topLeft, sideBlocks.topRight}){
					if (blockMask.block != null && blockMask.block.isSolid && Utils.intersects(blockMask.mask, newMask)){
						ySpeed = 0;
						y = blockMask.yPos + Block.WIDTH - (height-maskHeight)/2;
						break;
					}
				}
			}
		}
	}
	
	
	
	
	
	
	public Rectangle getNextMask(float xs, float ys){
		return new Rectangle((float)(x+(width-maskWidth)/2) + xs, (float)(y+(height-maskHeight)/2) + ys, (float)(maskWidth), (float)maskHeight);
	}
	
	public CollisionGroup getSideBlocks(Chunk prevChunk, Chunk currChunk, Chunk nextChunk, Rectangle nextMask){
		double relativeXPos = nextMask.getMinX() % Chunk.CHUNK_PIXEL_WIDTH;
		if (relativeXPos < Chunk.CHUNK_PIXEL_WIDTH - maskWidth){
			return currChunk.getCollidedSideBlocks(nextMask.getMinX(), nextMask.getMinY(), nextMask.getWidth(), nextMask.getHeight());
		} else {
			CollisionGroup group1 = currChunk.getCollidedLeftSideBlocks(nextMask.getMinX(), nextMask.getMinY(), nextMask.getWidth(), nextMask.getHeight());
			CollisionGroup group2 = nextChunk.getCollidedLeftSideBlocks(nextMask.getMinX()+Block.WIDTH, nextMask.getMinY(), nextMask.getWidth(), nextMask.getHeight());
			return new CollisionGroup(group1.topLeft, group2.topLeft, group1.bottomLeft, group2.bottomLeft);
		}
		
	}
	
	@Override
	public void render(double worldPos) {
		if (!(x+Block.WIDTH-worldPos<0 || x-Block.WIDTH-worldPos>Chunk.CHUNK_WIDTH*Block.WIDTH)){
			GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
			GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
			getTexture().bind();
			double renderX = x - worldPos;
			GL11.glColor3d((hP)/maxHP, (hP)/maxHP, (hP)/maxHP); // Could make this faster!!
			GL11.glBegin(GL11.GL_QUADS);
				GL11.glNormal3d(0, 0, 1);
				GL11.glTexCoord2d(0.0, 0.0);
				GL11.glVertex3d(renderX, y, zIndex);
				GL11.glTexCoord2d(1.0, 0.0);
				GL11.glVertex3d(renderX + getWidth(), y, zIndex);
				GL11.glTexCoord2d(1.0, 1.0);
				GL11.glVertex3d(renderX + getWidth(), y + getHeight(), zIndex);
				GL11.glTexCoord2d(0.0, 1.0);
				GL11.glVertex3d(renderX, y + getHeight(), zIndex);
			GL11.glEnd();
		}
	}
	
	public abstract Texture getTexture();
	
	public abstract double getWidth();
	public abstract double getHeight();

}
